package com.shenma2009.netty.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

/**
 * @author 12692
 * @version 1.0
 * @description: WebSocketClient
 * @date 2023/5/26 17:35
 */

public class WebSocketClient {
    private static ExecutorService executor = Executors.newCachedThreadPool();

    private String uri ;
    private CountDownLatch latch;
    private ClientInitializer clientInitializer;
    private Channel channel;
    private WebSocketClientHandler handler;

    private WebSocketClient(){
    }
    public WebSocketClient(String uri){
        this.uri = uri;
        latch = new CountDownLatch(0);
        clientInitializer = new ClientInitializer(latch);
    }

    public Channel getChannel() {
        return channel;
    }

    public void close() {
        if(channel != null) {
            channel.close();
            channel = null;
        }
    }

    public void open() {
        try {
            EventLoopGroup group=new NioEventLoopGroup();
            Bootstrap boot=new Bootstrap();
            boot.option(ChannelOption.SO_KEEPALIVE,true)
                    .option(ChannelOption.TCP_NODELAY,true)
                    .option(ChannelOption.SO_BACKLOG,1024*1024*10)
                    .group(group)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .channel(NioSocketChannel.class)
                    .handler(new ClientInitializer(latch));
            URI websocketURI = new URI(uri);
            HttpHeaders httpHeaders = new DefaultHttpHeaders();
            //进行握手
            WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(websocketURI, WebSocketVersion.V13, (String)null, true,httpHeaders);
            System.out.println("客户端：开始连接服务器....");
            channel = boot.connect(websocketURI.getHost(),websocketURI.getPort()).sync().channel();
            handler = (WebSocketClientHandler)channel.pipeline().get("websocketHandler");
            handler.setHandshaker(handshaker);
            handshaker.handshake(channel);
            //阻塞等待是否握手成功
            handler.handshakeFuture().sync();
            System.out.println("客户端：连接成功....");
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
        }
    }

    public boolean isAlive() {
        return (channel!=null);
    }

    public String pushMsg(String content) throws URISyntaxException, InterruptedException {

        return sendMsg(channel,handler,content);
    }

    public String sendMsg(Channel channel,WebSocketClientHandler handler,String content) throws InterruptedException {
        System.out.println("send msg:" + content);
        //发起线程发送消息
        executor.submit(new WebSocketCallable(channel, content));
        latch = new CountDownLatch(1);
        clientInitializer.setHandler(handler);
        clientInitializer.resetLathch(latch);
        //等待，当websocket服务端返回数据时唤醒屏障，并返回结果
//        latch.await();
        return clientInitializer.getServerResult();
    }


    /**
     * @description 测试websocket client 代码
     * @author 军哥
     * @date 2023/5/27 11:23
     * @version 1.0
     */
    public static void main(String[] args) throws InterruptedException, URISyntaxException {
        String result = "";
        WebSocketClient webSocketClient = new WebSocketClient("ws://localhost:12424/ws");
        // 返回结果
        result = webSocketClient.pushMsg("hello websocket");
        System.out.println("￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥"+ result);

        Channel channel = webSocketClient.getChannel();
        channel.close();
        System.out.println("￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥"+"关闭连接");
    }
}
